package com.bishe.app.modules.usersaledetail.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bishe.app.core.api.CommonResult;
import com.bishe.app.core.api.CommonPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bishe.app.core.enums.IsDel;
import com.bishe.app.core.utils.AppRunnerUtils;
import com.bishe.app.core.utils.Lock;
import com.bishe.app.modules.group.entity.Group;
import com.bishe.app.modules.group.model.GroupUserList;
import com.bishe.app.modules.group.service.GroupService;
import com.bishe.app.modules.groupDaySaleCount.entity.GroupDaySaleCount;
import com.bishe.app.modules.groupDaySaleCount.model.GroupDayCount;
import com.bishe.app.modules.groupDaySaleCount.service.GroupDaySaleCountService;
import com.bishe.app.modules.groupuser.entity.GroupUser;
import com.bishe.app.modules.groupuser.enums.GroupUserPosition;
import com.bishe.app.modules.groupuser.service.GroupUserService;
import com.bishe.app.modules.userSaleIncome.entity.UserSaleIncome;
import com.bishe.app.modules.userSaleIncome.service.UserSaleIncomeService;
import com.bishe.app.modules.user.entity.User;
import com.bishe.app.modules.user.service.UserService;
import com.bishe.app.modules.usersaledetail.model.MonthSaleDetailReq;
import com.bishe.app.modules.usersaledetail.model.UserSaleCreateCmd;
import com.bishe.app.modules.usersaledetail.model.UserSaleDeleteAllDTO;
import com.bishe.app.modules.usersaledetail.model.UserShopSaleItem;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import com.bishe.app.modules.usersaledetail.service.UserSaleDetailService;
import com.bishe.app.modules.usersaledetail.entity.UserSaleDetail;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.*;
import java.util.stream.Collectors;

import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;


/**
 * <p>
 * 用户销售明细 前端控制器
 * </p>
 *
 * @author
 * @since 2024-03-13
 */
@RestController
@RequestMapping("/userSaleDetail")
@Slf4j
public class UserSaleDetailController {

    @Autowired
    public UserSaleDetailService userSaleDetailService;

    @Resource
    private UserService userService;

    @Resource
    private GroupUserService groupUserService;

    @Resource
    private GroupService groupService;

    @Resource
    private UserSaleIncomeService saleIncomeService;

    @Resource
    private GroupDaySaleCountService groupDaySaleCountService;

    @RequestMapping(value = "/getGroupList", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<Group>> getGroupList() {
        User user = AppRunnerUtils.getUser();

        List<String> superNames = AppRunnerUtils.getSuperNames();


        // 获取用户的所有组织
        List<GroupUser> groupUserList = new ArrayList<>();
        if (superNames.contains(user.getName())) {
            // 获取用户的所有组织
            groupUserList = groupUserService.lambdaQuery()
                    .eq(GroupUser::getIsDel, IsDel.N.getCode())
                    .orderByDesc(GroupUser::getGroupId)
                    .list();
        } else {
            // 获取用户的所有组织
            groupUserList = groupUserService.lambdaQuery()
                .eq(GroupUser::getUserId, user.getId())
                .eq(GroupUser::getIsDel, IsDel.N.getCode())
                .orderByDesc(GroupUser::getGroupId)
                .list();
        }



        if (CollectionUtils.isEmpty(groupUserList)) {
            return CommonResult.success(new ArrayList<>());
        }
        List<Long> groupIdList = groupUserList.stream()
                .map(gu -> gu.getGroupId())
                .collect(Collectors.toList());


        List<Group> groupList = groupService.lambdaQuery()
                .in(Group::getId, groupIdList)
                .eq(Group::getIsDel, IsDel.N.getCode())
                .list();

        return CommonResult.success(groupList);
    }

    @RequestMapping(value = "/getMonthSaleDetails/v2", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult getGroupSaleDetail(@RequestBody MonthSaleDetailReq req) {
        // 获取用户
//        User user = AppRunnerUtils.getUser();
//
//        // 获取用户的组织类型和列表
//        List<GroupUser> groupUsers = groupUserService.lambdaQuery()
//                .eq(GroupUser::getUserId, user.getId())
//                .eq(GroupUser::getIsDel, IsDel.N.getCode())
//                .orderByDesc(GroupUser::getGroupId)
//                .list();
//
//        if (CollectionUtils.isEmpty(groupUsers)) {
//            throw new BizException("您不属于任何组织，请联系管理员添加!");
//        }

        // 拿到所有的用户
        List<GroupUser> groupUserList = groupUserService.lambdaQuery()
                .eq(GroupUser::getGroupId, req.getGroupId())
                .eq(GroupUser::getIsDel, IsDel.N.getCode())
                .list();

        List<Long> userIds = groupUserList.stream()
                .sorted((o1, o2) -> o2.getLeader().compareTo(o1.getLeader()))
                .map(GroupUser::getUserId)
                // 店长放入最后
                .collect(Collectors.toList());


        List<GroupDaySaleCount> groupSaleCountList = groupDaySaleCountService.lambdaQuery()
                .eq(GroupDaySaleCount::getYear, req.getYear())
                .eq(GroupDaySaleCount::getMon, req.getMon())
                .eq(GroupDaySaleCount::getGroupId, req.getGroupId())
                .eq(GroupDaySaleCount::getIsDel, IsDel.N.getCode())
                .list();

        // 初始化当前销售map
        List<Map<String, Object>> saleDetails = new ArrayList<>();

        // 获取当前月份所有的天
        YearMonth yearMonth = YearMonth.of(req.getYear(), req.getMon());
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.atEndOfMonth();
        List<LocalDate> allDays = new ArrayList<>();
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            allDays.add(date);

            HashMap<String, Object> curMap = new HashMap<>();
            curMap.put("day", date.getDayOfMonth());
            curMap.put("date", date.toString());
            saleDetails.add(curMap);
        }

        // 开始获取每个用户的销售额
        for (Long userId : userIds) {
            // getUserSale
            List<UserSaleDetail> userMonthSaleList = userSaleDetailService.lambdaQuery()
                    .eq(UserSaleDetail::getYear, req.getYear())
                    .eq(UserSaleDetail::getMon, req.getMon())
                    .eq(UserSaleDetail::getUserId, userId)
                    .eq(UserSaleDetail::getIsDel, IsDel.N.getCode())
                    .list();

            // 获取当天的销售额
            for (Map<String, Object> saleDayDetail : saleDetails) {
                Integer day = (Integer) saleDayDetail.get("day");

                UserShopSaleItem userShopSaleItem = userMonthSaleList.stream()
                        .filter(x -> Objects.equals(x.getDay(), day))
                        .findFirst()
                        .map(x -> UserShopSaleItem.getShopSale(x))
                        .orElse(UserShopSaleItem.getDefaultShopSale());


                GroupDayCount groupDayCount = groupSaleCountList.stream()
                        .filter(x -> Objects.equals(x.getDay(), day))
                        .findFirst()
                        .map(t -> GroupDayCount.fromCountEntity(t))
                        .orElse(GroupDayCount.init());
                saleDayDetail.put("saleA", groupDayCount.getSaleA());
                saleDayDetail.put("saleB", groupDayCount.getSaleB());


                // 职位需要返回,因为要判断展示
                GroupUser groupUser = groupUserService.lambdaQuery()
                        .eq(GroupUser::getGroupId, req.getGroupId())
                        .eq(GroupUser::getUserId, userId)
                        .eq(GroupUser::getIsDel, IsDel.N.getCode())
                        .one();

                JSONObject jsonObject = new JSONObject();
                jsonObject.putAll(JSON.parseObject(JSON.toJSONString(groupUser)));
                jsonObject.putAll(JSON.parseObject(JSON.toJSONString(userShopSaleItem)));

                saleDayDetail.put("user" + userId, jsonObject);
            }
        }

        // 返回销售额
        return CommonResult.success(saleDetails);
    }


    /**
     * 获取组织的每天统计
     *
     * @param req
     * @return
     */
    @RequestMapping(value = "/getGroupSaleCount/v2", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult getGroupMonthDayCount(MonthSaleDetailReq req) {
//        // 获取用户
//        User user = AppRunnerUtils.getUser();
//
//        // 获取用户的组织类型和列表
//        List<GroupUser> groupUsers = groupUserService.lambdaQuery()
//                .eq(GroupUser::getUserId, user.getId())
//                .eq(GroupUser::getIsDel, IsDel.N.getCode())
//                .orderByDesc(GroupUser::getGroupId)
//                .list();
//
//        if (CollectionUtils.isEmpty(groupUsers)) {
//            throw new BizException("您不属于任何组织，请联系管理员添加!");
//        }

        List<GroupDaySaleCount> groupSaleCountList = groupDaySaleCountService.lambdaQuery()
                .eq(GroupDaySaleCount::getYear, req.getYear())
                .eq(GroupDaySaleCount::getMon, req.getMon())
                .eq(GroupDaySaleCount::getGroupId, req.getGroupId())
                .eq(GroupDaySaleCount::getIsDel, IsDel.N.getCode())
                .list();

        // 初始化当前销售map
        List<Map<String, Object>> saleDetails = new ArrayList<>();

        // 获取当前月份所有的天
        YearMonth yearMonth = YearMonth.of(req.getYear(), req.getMon());
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.atEndOfMonth();
        List<LocalDate> allDays = new ArrayList<>();
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            allDays.add(date);

            HashMap<String, Object> curMap = new HashMap<>();
            curMap.put("day", date.getDayOfMonth());
            curMap.put("date", date.toString());


            GroupDayCount groupDayCount = groupSaleCountList.stream()
                    .filter(x -> Objects.equals(x.getDay(), curMap.get("day")))
                    .findFirst()
                    .map(x -> JSON.parseObject(x.getSaleItem(), GroupDayCount.class))
                    .orElse(GroupDayCount.init());

            curMap.put("saleA", groupDayCount.getSaleA());
            curMap.put("saleB", groupDayCount.getSaleB());

            saleDetails.add(curMap);
        }

        return CommonResult.success(saleDetails);
    }


    @RequestMapping(value = "/getMonthSaleDetails", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult getMonthSaleDetails(@RequestBody  MonthSaleDetailReq req) {
        if (req.getYear() == null) {
            req.setYear(LocalDateTime.now().getYear());
        }

        if (req.getMon() == null) {
            req.setMon(LocalDateTime.now().getMonthValue());
        }

        // 获取用户
//        User user = AppRunnerUtils.getUser();
//
//        // 获取用户的组织类型和列表
//        List<GroupUser> groupUsers = groupUserService.lambdaQuery()
//                .eq(GroupUser::getUserId, user.getId())
//                .eq(GroupUser::getIsDel, IsDel.N.getCode())
//                .orderByDesc(GroupUser::getGroupId)
//                .list();
//
//        if (CollectionUtils.isEmpty(groupUsers)) {
//            throw new BizException("您不属于任何组织，请联系管理员添加!");
//        }


        // obtain DB
        // get SHOP
        List<GroupUser> groupUserList = groupUserService.lambdaQuery()
//                .eq(GroupUser::getUserId, user.getId())
                .eq(GroupUser::getGroupId, req.getGroupId())
                .eq(GroupUser::getIsDel, IsDel.N.getCode())
                .list();

        if (CollectionUtils.isEmpty(groupUserList)) {
            return CommonResult.failed("当前组织无人员，请联系管理员添加!");
        }

        Group group = groupService.getById(req.getGroupId());


        List<Long> userIds = groupUserList.stream()
                .sorted((o1, o2) -> o2.getLeader().compareTo(o1.getLeader()))
                .map(GroupUser::getUserId)
                // 店长放入最后
                .collect(Collectors.toList());


        // 初始化当前销售map
        List<Map<String, Object>> saleDetails = new ArrayList<>();

        // 获取当前月份所有的天
        YearMonth yearMonth = YearMonth.of(req.getYear(), req.getMon());
        LocalDate startDate = yearMonth.atDay(1);
        LocalDate endDate = yearMonth.atEndOfMonth();
        List<LocalDate> allDays = new ArrayList<>();
        for (LocalDate date = startDate; !date.isAfter(endDate); date = date.plusDays(1)) {
            allDays.add(date);

            HashMap<String, Object> curMap = new HashMap<>();
            curMap.put("day", date.getDayOfMonth());
            curMap.put("date", date.toString());
            saleDetails.add(curMap);
        }


        for (Long userId : userIds) {
            // getUserInfo
            User userInfo = userService
                    .getById(userId);
            // getUserSale
            List<UserSaleDetail> allSaleList = userSaleDetailService.lambdaQuery()
                    .eq(UserSaleDetail::getYear, req.getYear())
                    .eq(UserSaleDetail::getMon, req.getMon())
                    .eq(UserSaleDetail::getUserId, userId)
                    .eq(UserSaleDetail::getIsDel, IsDel.N.getCode())
                    .list();

            saveToListMap(saleDetails, userInfo, allSaleList, groupUserList);
        }

        return CommonResult.success(saleDetails);
    }

    private void saveToListMap(List<Map<String, Object>> saleDetails, User userInfo, List<UserSaleDetail> allSaleList,
                               List<GroupUser> groupUserList) {
        saleDetails.forEach(map -> {
            // {
            //            "id": 111,
            //            "userName": 222,
            //            "saleA": 1111,
            //            "saleB": 2222
            //          }
            String date = (String) map.get("date");

            // 放入用户
            GroupUser groupUser = groupUserList.stream().filter(x -> x.getUserId().equals(userInfo.getId()))
                    .findFirst().get();
            userInfo.setPwd("");
            GroupUserList gul = new GroupUserList();
            BeanUtils.copyProperties(userInfo, gul);
            gul.setLeaderId(groupUser.getLeader());
            gul.setLeaderName(GroupUserPosition.ofCode(groupUser.getLeader()).getDesc());

            UserShopSaleItem userShopSaleItem = Optional.ofNullable(allSaleList)
                    .orElse(new ArrayList<>()).stream()
                    .filter(x -> Objects.equals(x.getDate(), date))
                    .findAny()
                    .map(x -> UserShopSaleItem.getShopSale(x))
                    .orElse(UserShopSaleItem.getDefaultShopSale());


            Map<String, Object> userMap = new HashMap<>();
            userMap.put("saleItem", userShopSaleItem);
            userMap.put("groupUser", gul);

            map.put("user" + userInfo.getId(), userMap);
        });
    }


    @RequestMapping(value = "/deleteAll", method = RequestMethod.POST)
    @ResponseBody
    @Transactional(rollbackFor = Throwable.class)
    @Lock(lockPrefix = "/userSaleDetail", key = "#userSaleDeleteAllDTO.groupId", lockSecond = 60)
    public CommonResult create(@RequestBody UserSaleDeleteAllDTO userSaleDeleteAllDTO) {
        if (userSaleDeleteAllDTO.getGroupId() == null) {
            return CommonResult.failed("groupId不能为空");
        }

        if (userSaleDeleteAllDTO.getCurMon() == null) {
            return CommonResult.failed("月份不能为空");
        }

        Long groupId = userSaleDeleteAllDTO.getGroupId();
        Integer year = Integer.parseInt(userSaleDeleteAllDTO.getCurMon().split("-")[0]);
        Integer mon = Integer.parseInt(userSaleDeleteAllDTO.getCurMon().split("-")[1]);

        List<GroupUser> guList = groupUserService.lambdaQuery()
                .eq(GroupUser::getGroupId, groupId)
                .eq(GroupUser::getIsDel, IsDel.N.getCode())
                .list();


        if (CollectionUtils.isEmpty(guList)) {
            return CommonResult.success(null);
        }

        groupDaySaleCountService.lambdaUpdate()
                .eq(GroupDaySaleCount::getGroupId, groupId)
                .eq(GroupDaySaleCount::getYear, year)
                .eq(GroupDaySaleCount::getMon, mon)
                .set(GroupDaySaleCount::getIsDel, IsDel.Y.getCode())
                .update();

        Set<Long> curUserList = guList.stream().map(GroupUser::getUserId).collect(Collectors.toSet());
        // 删除销售
        userSaleDetailService.lambdaUpdate()
                .in(UserSaleDetail::getUserId, curUserList)
                .eq(UserSaleDetail::getYear, year)
                .eq(UserSaleDetail::getMon, mon)
                .set(UserSaleDetail::getIsDel, IsDel.Y.getCode())
                .update();

        // 删除收入
        saleIncomeService.lambdaUpdate()
                .eq(UserSaleIncome::getGroupId, groupId)
                .eq(UserSaleIncome::getYear, year)
                .eq(UserSaleIncome::getMon, mon)
                .set(UserSaleIncome::getIsDel, IsDel.Y.getCode())
                .update();

        return CommonResult.success(null);
    }


    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    @Lock(lockPrefix = "/userSaleDetail",key = "#userSaleDetail.userId", lockSecond = 60)
    public CommonResult create(@RequestBody UserSaleDetail userSaleDetail) {
        boolean success = userSaleDetailService.save(userSaleDetail);
        if (success) {
            return CommonResult.success(null);
        }
        return CommonResult.failed();
    }

    @RequestMapping(value = "/createSaleDetail", method = RequestMethod.POST)
    @ResponseBody
    @Transactional(rollbackFor = Throwable.class)
    @Lock(lockPrefix = "/userSaleDetail",key = "#userSaleCreateCmd.userId", lockSecond = 60)
    public CommonResult create(@RequestBody UserSaleCreateCmd userSaleCreateCmd) {
        // TODO: jeffrey. 增加Lock
        UserSaleDetail sd = new UserSaleDetail();
        sd.setUserId(userSaleCreateCmd.getUserId());

        UserShopSaleItem userShopSaleItem = new UserShopSaleItem();
        userShopSaleItem.setSale(userSaleCreateCmd.getSale());
        userShopSaleItem.setSaleSingle(Optional.ofNullable(userSaleCreateCmd.getSaleSingle()).orElse("0"));
        sd.setSaleItem(JSON.toJSONString(userShopSaleItem));
        sd.setDate(userSaleCreateCmd.getDate());

        String[] dateArr = userSaleCreateCmd.getDate().split("-");

        sd.setYear(Integer.valueOf(dateArr[0]));
        sd.setMon(Integer.valueOf(dateArr[1]));
        sd.setDay(Integer.valueOf(dateArr[2]));

        UserSaleDetail dbSaleEntity = userSaleDetailService.lambdaQuery()
                .eq(UserSaleDetail::getUserId, userSaleCreateCmd.getUserId())
                .eq(UserSaleDetail::getDate, userSaleCreateCmd.getDate())
                .eq(UserSaleDetail::getIsDel, IsDel.N.getCode())
                .one();
        boolean success = false;
        if (dbSaleEntity == null) {
            success = userSaleDetailService.save(sd);
        } else {
            dbSaleEntity.setSaleItem(JSON.toJSONString(userShopSaleItem));
            success = userSaleDetailService.updateById(dbSaleEntity);
        }

        if (success) {
            // 计算业绩
            // 如果是店铺
            saleIncomeService.calcIncome(userSaleCreateCmd.getGroupId(), userSaleCreateCmd.getUserId(),
                    sd.getYear(), sd.getMon());
            return CommonResult.success(null);
        }
        return CommonResult.failed();
    }

    @RequestMapping(value = "/update/{id}", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult update(@PathVariable Long id, @RequestBody UserSaleDetail userSaleDetail) {
        userSaleDetail.setId(id);
        boolean success = userSaleDetailService.updateById(userSaleDetail);
        if (success) {
            return CommonResult.success(null);
        }
        return CommonResult.failed();
    }

    @RequestMapping(value = "/delete/{id}", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult delete(@PathVariable Long id) {
        boolean success = userSaleDetailService.removeById(id);
        if (success) {
            return CommonResult.success(null);
        }
        return CommonResult.failed();
    }

    @RequestMapping(value = "/delete", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult deleteBatch(@RequestParam("ids") List<Long> ids) {
        boolean success = userSaleDetailService.removeByIds(ids);
        if (success) {
            return CommonResult.success(null);
        }
        return CommonResult.failed();
    }


    @RequestMapping(value = "/listAll", method = RequestMethod.GET)
    @ResponseBody
    public CommonResult<List<UserSaleDetail>> listAll() {
        List<UserSaleDetail> userSaleDetailList = userSaleDetailService.list();
        return CommonResult.success(userSaleDetailList);
    }

    @RequestMapping(value = "/pageList", method = RequestMethod.POST)
    @ResponseBody
    public CommonResult<CommonPage<UserSaleDetail>> page(@RequestBody CommonPage commonPage) {
        Page<UserSaleDetail> page = new Page(commonPage.getPageNum(), commonPage.getPageSize());
        return CommonResult.success(CommonPage.restPage(userSaleDetailService.page(page)));
    }
}



